﻿using System;
using System.Collections.Generic;

namespace EndlessGalaxy
{
    public class Planet
    {
        public enum worldType
        {
            star, neutronstar, bHole, rockyWorld, asteroidbelt, wisp, debris,
            dwarfplanet, gasGiant, moon, asteroidmoon, spacestation, comet, NullRef
        };
        public worldType type;
        public List<Cargo> composition;
        public List<Cargo> surface; // Biomatter, topsoil, water, etc etc etc
        public List<Cargo> atmosphere; // work out heavy and light gases, possibly just using density, as well as greenhouse ones to change temp
        public bool hasColony;
        public List<Facility> facilities;
        public List<Cargo> storage;
        public double aveTemp;
        public double roughness; //Determines single-biome-ness.  Higher roughness means more biomes
        public bool constructed; //like, space stations.
        public double radiation;
        public double radius;
        public double gravity;
        public System.Drawing.Point location;//for skybox placement
        public System.Drawing.Color color;
        public int imgsize;
        public string name;
        public string shortname;
        public int homeindex;
        public double population;

        public Planet(worldType Type)
        {
            type = Type;
            double volume = 0.0;
            List<string> names;
            List<string> names2; //This one keeps count, and is used to determine planet variability
            int count;
            double multiplier = 4;
            composition = new List<Cargo>();
            surface = new List<Cargo>();
            atmosphere = new List<Cargo>();
            switch (type)
            {
                case worldType.bHole:
                    foreach (SuperCargo stuff in Globals.materials.Values)
                    {
                        if (stuff.attributes.Contains("NEUTRON"))
                        {
                            composition.Add(new Cargo(stuff.name,
                                (1.44 + (10 * Globals.randint.NextDouble()) * Globals.solarmass),
                                Cargo.Phases.solid));
                            break;
                        }
                    }
                    radiation = Globals.randint.Next(5000000, 10000001);
                    radius = (2 * (0.0000000000667384) * Gravity()) / (89875517873681764.0);
                    color = System.Drawing.Color.DarkSlateGray;
                    break;
                case worldType.neutronstar:
                    foreach (SuperCargo stuff in Globals.materials.Values)
                    {
                        if (stuff.attributes.Contains("NEUTRON"))
                        {
                            composition.Add(new Cargo(stuff.name,
                                (1.44 + (10 * Globals.randint.NextDouble()) * Globals.solarmass),
                                Cargo.Phases.solid));
                            break;
                        }
                    }
                    radiation = Globals.randint.Next(2500000, 10000001);
                    radius = Math.Pow(((4.0 / 3.0) * (1 / (composition[0].density / composition[0].amount)) * Math.PI), (1.0 / 3.0));
                    color = System.Drawing.Color.DarkRed;
                    break;
                case worldType.star:
                    gravity = (Globals.randint.NextDouble() * Globals.solarmass * 10.0);
                    composition = Cargo.StellarMass(gravity / Globals.solarmass);
                    radiation = Globals.randint.Next(2500000, 7500001);
                    radius = Math.Pow(((4.0 / 3.0) * (((1 / (composition[0].density / composition[0].amount)) +
                        (1 / (composition[1].density / composition[1].amount))) / 2) * Math.PI), (1.0 / 3.0));
                    color = System.Drawing.Color.Yellow;
                    break;
                case worldType.gasGiant:
                    #region gases
                    names = new List<string>();
                    names2 = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("GASGIANT_COMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("GASGIANT_UNCOMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("GASGIANT_RARE"))
                        {
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                    }
                    for (count = Globals.randint.Next(1, names2.Count + 1); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(1000000.0, multiplier), Cargo.Phases.gas));
                        multiplier *= Math.Pow(Globals.randint.NextDouble(), (1.0 / 6.0));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    #region traces
                    names = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("GASGIANT_TRACE"))
                        {
                            names.Add(items.name);
                        }
                    }
                    foreach (Cargo stuff in composition)
                    {
                        gravity += stuff.amount;
                    }
                    for (count = Globals.randint.Next(0, names.Count + 1); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(gravity, (1.0 / 3.0)), Cargo.Phases.gas));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    color = System.Drawing.Color.Chocolate;
                    roughness = Globals.randint.NextDouble();
                    volume = 0.0;
                    foreach (Cargo stuff in composition)
                    {
                        volume += 1 / (stuff.density / stuff.amount);
                    }
                    radius = Math.Pow(((4.0 / 3.0) * (volume / composition.Count) * Math.PI), (1.0 / 3.0));
                    break;
                case worldType.rockyWorld:
                    #region rocks
                    names = new List<string>();
                    names2 = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("PLANETARY_COMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("PLANETARY_UNCOMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("PLANETARY_RARE"))
                        {
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                    }
                    for (count = Globals.randint.Next(1, names2.Count-1); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(200000.0, multiplier), Cargo.Phases.solid));
                        multiplier *= Math.Pow(Globals.randint.NextDouble(),(1.0/6.0));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    #region traces
                    names = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("PLANETARY_TRACE"))
                        {
                            names.Add(items.name);
                        }
                    }
                    foreach (Cargo stuff in composition)
                    {
                        gravity += stuff.amount;
                    }
                    for (count = Globals.randint.Next(0, names.Count + 1); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(gravity, (1.0 / 3.0)), Cargo.Phases.solid));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    #region surface
                    multiplier = 4.0;
                    names = new List<string>();
                    names2 = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("SURFACE_COMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("SURFACE_UNCOMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("SURFACE_RARE"))
                        {
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                    }
                    for (count = Globals.randint.Next(names2.Count); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        surface.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(34000.0, multiplier), Globals.materials[names[i]].phase));
                        multiplier *= Math.Pow(Globals.randint.NextDouble(), (1.0 / 6.0));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    #region traces
                    names = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("SURFACE_TRACE"))
                        {
                            names.Add(items.name);
                        }
                    }
                    foreach (Cargo stuff in surface)
                    {
                        gravity += stuff.amount;
                    }
                    for (count = Globals.randint.Next(0, names.Count + 1); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        surface.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(gravity, (1.0 / 3.0)), Globals.materials[names[i]].phase));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    #region atmo
                    multiplier = 4.0;
                    names = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("ATMOSPHERE"))
                        {
                            names.Add(items.name);
                        }
                    }
                    for (count = Globals.randint.Next(1, Math.Min(names.Count + 1, 6)); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        atmosphere.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(20000.0, multiplier), Cargo.Phases.gas));
                        multiplier *= Math.Pow(Globals.randint.NextDouble(), (1.0 / 6.0));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    color = System.Drawing.Color.Green;
                    roughness = Globals.randint.NextDouble();
                    volume = 0.0;
                    foreach (Cargo stuff in composition)
                    {
                        volume += 1 / (stuff.density / stuff.amount);
                    }
                    radius = Math.Pow(((4.0 / 3.0) * (volume / composition.Count) * Math.PI), (1.0 / 3.0));
                    break;
                case worldType.asteroidbelt:
                    #region rocks
                    names = new List<string>();
                    names2 = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("PLANETARY_COMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("PLANETARY_UNCOMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("PLANETARY_RARE"))
                        {
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                    }
                    for (count = Globals.randint.Next(1, names2.Count - 1); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(200000.0, multiplier), Cargo.Phases.solid));
                        multiplier *= Math.Pow(Globals.randint.NextDouble(), (1.0 / 6.0));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    #region traces
                    names = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("PLANETARY_TRACE"))
                        {
                            names.Add(items.name);
                        }
                    }
                    foreach (Cargo stuff in composition)
                    {
                        gravity += stuff.amount;
                    }
                    for (count = Globals.randint.Next(0, Math.Min(names.Count + 1, 7)); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(gravity, (1.0 / 3.0)), Cargo.Phases.solid));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    color = System.Drawing.Color.FromArgb(128, 128, 128, 128);
                    roughness = Globals.randint.NextDouble();
                    volume = 0.0;
                    foreach (Cargo stuff in composition)
                    {
                        volume += 1 / (composition[0].density / composition[0].amount);
                    }
                    radius = Math.Pow(((4.0 / 3.0) * (volume / composition.Count) * Math.PI), (1.0 / 2.0));
                    break;
                case worldType.comet:
                    #region rocks
                    names = new List<string>();
                    names2 = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("COMET_COMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("COMET_UNCOMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("COMET_RARE"))
                        {
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                    }
                    for (count = Globals.randint.Next(1, names2.Count - 1); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(500.0, multiplier), Cargo.Phases.solid));
                        multiplier *= Math.Pow(Globals.randint.NextDouble(), (1.0 / 6.0));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    #region traces
                    names = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("COMET_TRACE"))
                        {
                            names.Add(items.name);
                        }
                    }
                    foreach (Cargo stuff in composition)
                    {
                        gravity += stuff.amount;
                    }
                    for (count = Globals.randint.Next(0, Math.Min(names.Count + 1, 7)); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(gravity, (1.0 / 3.0)), Cargo.Phases.solid));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    color = System.Drawing.Color.Aqua;
                    roughness = Globals.randint.NextDouble();
                    volume = 0.0;
                    foreach (Cargo stuff in composition)
                    {
                        volume += 1 / (stuff.density / stuff.amount);
                    }
                    radius = Math.Pow(((4.0 / 3.0) * (volume / composition.Count) * Math.PI), (1.0 / 2.0));
                    break;
                case worldType.dwarfplanet:
                    #region rocks
                    names = new List<string>();
                    names2 = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("PLANETARY_COMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("PLANETARY_UNCOMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("PLANETARY_RARE"))
                        {
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                    }
                    for (count = Globals.randint.Next(1, names2.Count - 1); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(400.0, multiplier), Cargo.Phases.solid));
                        multiplier *= Math.Pow(Globals.randint.NextDouble(), (1.0 / 6.0));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    #region traces
                    names = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("PLANETARY_TRACE"))
                        {
                            names.Add(items.name);
                        }
                    }
                    foreach (Cargo stuff in composition)
                    {
                        gravity += stuff.amount;
                    }
                    for (count = Globals.randint.Next(0, Math.Min(names.Count + 1, 7)); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(gravity, (1.0 / 3.0)), Cargo.Phases.solid));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    color = System.Drawing.Color.Gray;
                    roughness = Globals.randint.NextDouble();
                    volume = 0.0;
                    foreach (Cargo stuff in composition)
                    {
                        volume += 1 / (stuff.density / stuff.amount);
                    }
                    radius = Math.Pow(((4.0 / 3.0) * (volume / composition.Count) * Math.PI), (1.0 / 2.0));
                    break;
                case worldType.moon:
                    #region rocks
                    names = new List<string>();
                    names2 = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("PLANETARY_COMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("PLANETARY_UNCOMMON"))
                        {
                            names.Add(items.name);
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                        if (items.attributes.Contains("PLANETARY_RARE"))
                        {
                            names.Add(items.name);
                            names2.Add(items.name);
                        }
                    }
                    for (count = Globals.randint.Next(1, names2.Count - 1); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(400.0, multiplier), Cargo.Phases.solid));
                        multiplier *= Math.Pow(Globals.randint.NextDouble(), (1.0 / 6.0));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    #region traces
                    names = new List<string>();
                    foreach (SuperCargo items in Globals.materials.Values)
                    {
                        if (items.attributes.Contains("PLANETARY_TRACE"))
                        {
                            names.Add(items.name);
                        }
                    }
                    foreach (Cargo stuff in composition)
                    {
                        gravity += stuff.amount;
                    }
                    for (count = Globals.randint.Next(0, Math.Min(names.Count + 1, 7)); count > 0; count--)
                    {
                        int i = Globals.randint.Next(names.Count);
                        composition.Add(new Cargo(names[i], Globals.randint.NextDouble() * Math.Pow(gravity, (1.0 / 3.0)), Cargo.Phases.solid));
                        string n = names[i];
                        while (names.Contains(n))
                        {
                            names.Remove(n);
                        }
                        if (names.Count < 1)
                        {
                            break;
                        }
                    }
                    #endregion
                    color = System.Drawing.Color.LightGray;
                    roughness = Globals.randint.NextDouble();
                    volume = 0.0;
                    foreach (Cargo stuff in composition)
                    {
                        volume += 1 / (stuff.density / stuff.amount);
                    }
                    radius = Math.Pow(((4.0 / 3.0) * (volume / composition.Count) * Math.PI), (1.0 / 2.0));
                    break;
            }
            foreach (Cargo junk in composition)
            {
                junk.amount = Math.Round(junk.amount);
            }
            foreach (Cargo junk in atmosphere)
            {
                junk.amount = Math.Round(junk.amount);
            }
            foreach (Cargo junk in surface)
            {
                junk.amount = Math.Round(junk.amount);
            }
            for (int i = composition.Count - 1; i >= 0; i--)
            {
                if (composition[i].amount < 1)
                {
                    composition.RemoveAt(i);
                    continue;
                }
            }
            for (int i = surface.Count - 1; i >= 0; i--)
            {
                if (surface[i].amount < 1)
                {
                    surface.RemoveAt(i);
                    continue;
                }
            }
            for (int i = atmosphere.Count - 1; i >= 0; i--)
            {
                if (atmosphere[i].amount < 1)
                {
                    atmosphere.RemoveAt(i);
                    continue;
                }
            }
        }

        public Planet(worldType Type, Cargo materials, System.Drawing.Point Location)
        {
            type = Type;
            composition = new List<Cargo>() { materials };
            surface = new List<Cargo>();
            atmosphere = new List<Cargo>();
            color = System.Drawing.Color.Crimson;
            double volume = 1 / (composition[0].density / composition[0].amount);
            radius = Math.Max(Math.Pow(((4.0 / 3.0) * (volume / composition.Count) * Math.PI), (1.0 / 2.0)), 1);
            if ((radius <= 0.0) || (double.IsNaN(radius)) || (double.IsInfinity(radius)))
            {
                radius = 1.0;
            }
            location = Location;
            imgsize = Convert.ToInt32(Math.Max(Math.Log(radius, 5.0), 2.0));
            name = "Unnamed Object";
            switch (type)
            {
                case worldType.bHole:
                    color = System.Drawing.Color.DarkSlateGray;
                    break;
                case worldType.neutronstar:
                    color = System.Drawing.Color.DarkRed;
                    break;
                case worldType.star:
                    color = System.Drawing.Color.Yellow;
                    break;
                case worldType.gasGiant:
                    color = System.Drawing.Color.Chocolate;
                    break;
                case worldType.rockyWorld:
                    color = System.Drawing.Color.Green;
                    break;
                case worldType.asteroidbelt:
                    color = System.Drawing.Color.FromArgb(128, 128, 128, 128);
                    break;
                case worldType.comet:
                    color = System.Drawing.Color.Aqua;
                    break;
                case worldType.dwarfplanet:
                    color = System.Drawing.Color.Gray;
                    break;
                case worldType.moon:
                    color = System.Drawing.Color.LightGray;
                    break;
            }
        }

        public double Habitability(Species spec)
        {
            //double atmoMatch = Math.Min(
            //List<Cargo> reqs = Globals.Copy(spec.atmorequirements);
            //foreach (Cargo thing in AtmoBottom())
            //{
            //    difference =
            //}
            return 0.0;//temp
        }

        public List<Cargo> AtmoBottom()
        {
            List<Cargo> air = new List<Cargo>();
            double maxDens = 0;
            foreach (Cargo thing in atmosphere)
            {
                if (thing.density > maxDens)
                {
                    maxDens = thing.density;
                }
            }
            foreach (Cargo thing in atmosphere)
            {
                air.Add(new Cargo(thing, ((thing.density / maxDens) * thing.amount)));
            }
            return air;
        }

        public List<Cargo> CompositionTop()
        {
            List<Cargo> rocks = new List<Cargo>();
            double minDens = Double.MaxValue;
            foreach (Cargo thing in composition)
            {
                if (thing.density < minDens)
                {
                    minDens = thing.density;
                }
            }
            foreach (Cargo thing in composition)
            {
                rocks.Add(new Cargo(thing, ((minDens / thing.density) * thing.amount)));
            }
            return rocks;
        }

        public double AmountOf(string cargoname)
        {
            foreach (Cargo stuff in composition)
            {
                if (stuff.name == cargoname)
                {
                    return stuff.amount;
                }
            }
            return 0.0;
        }

        public double Mass()
        {
            return Gravity();
        }

        public override string ToString()
        {
            return name;
        }

        public double Gravity()
        {
            return Cargo.Sum(composition);
        }

        public Cargo GiveRandomCargo(double amount)
        {
            Cargo output;
            int i = Globals.randint.Next(0, composition.Count);
            output = new Cargo(composition[i], amount);
            composition[i].amount -= amount;
            if (composition[i].amount <= 0)
            {
                output.amount += composition[i].amount;
                composition.RemoveAt(i);
            }
            if (composition.Count < 1)
            {
                type = worldType.NullRef;
            }
            return output;
        }

        public void Reevaluate(int stars)
        {
            //Figure out here how to algorithmically calculate what type of planet this is. It will be reassigned.
            //Highly dangerous when adding to a neutron star.
            switch (type)
            {
                case worldType.dwarfplanet:
                case worldType.rockyWorld:
                    if (atmosphere.Count > 0)
                    {
                        type = worldType.rockyWorld;
                    }
                    else
                    {
                        if (Mass() > Math.Pow(10, 15))
                        {
                            type = worldType.rockyWorld;
                        }
                        else
                        {
                            type = worldType.dwarfplanet;
                        }
                    }
                    goto default;
                default:
                    double volume = 0.0;
                    foreach (Cargo stuff in composition)
                    {
                        volume += 1 / (stuff.density / stuff.amount);
                    }
                    if ((type != worldType.star) && (type != worldType.rockyWorld) && (type != worldType.neutronstar) && (type != worldType.gasGiant))
                    {
                        radius = Math.Pow(((4.0 / 3.0) * (volume / composition.Count) * Math.PI), (1.0 / 2.0));
                    }
                    else
                    {
                        radius = Math.Pow(((4.0 / 3.0) * (volume / composition.Count) * Math.PI), (1.0 / 3.0));
                    }
                    if (type == worldType.star)
                    {
                        imgsize = Math.Max(Convert.ToInt32(Math.Max(Math.Log(radius, 5.0), 1.0)), 3);//star
                    }
                    else
                    {
                        imgsize = Convert.ToInt32(Math.Max(Math.Log(radius, 5.0), 2.0));//planet
                    }
                    break;
            }
            //radiation = 10000 * stars / Globals.DistanceFromCenter(location);//When you get back: Alter this so it runs in Skybox, and accounts for stars of different radiation levels
            //foreach (Cargo stuff in atmosphere)
            //{
            //    radiation /= Math.Pow((stuff.amount * stuff.density), 0.01);
            //}
            //aveTemp = radiation;
            //foreach (Cargo stuff in atmosphere)
            //{
            //    if (Globals.materials[stuff.name].attributes.Contains("GREENHOUSE"))
            //    {
            //        aveTemp *= Math.Pow(stuff.amount, 0.01);
            //    }
            //}
        }

        public bool AddColony(List<Facility> facs)
        {
            if (hasColony)
            {
                return false;
            }
            else
            {
                facilities = new List<Facility>();
                hasColony = true;
                foreach (Facility that in facs)
                {
                    if (Math.Pow(radius, (1.0 / 3.0)) > facilities.Count)
                    {
                        facilities.Add(that);
                    }
                }
                return true;
            }
        }
    }
}